/**
 * 全局错误处理中间件
 */

import type { Context } from 'elysia';
import { ApiError, ErrorType, Logger } from '../utils/response';

/**
 * 错误处理中间件
 */
export function errorHandler(error: any, { set }: Context) {
  Logger.error('API Error occurred:', {
    message: error.message,
    stack: error.stack,
    type: error.type || 'Unknown'
  });

  // 处理自定义API错误
  if (error instanceof ApiError) {
    set.status = error.statusCode;
    return {
      success: false,
      message: error.message,
      error: error.details,
      code: error.type,
      timestamp: new Date().toISOString()
    };
  }

  // 处理数据库错误
  if (error.code) {
    const dbError = handleDatabaseError(error);
    set.status = dbError.statusCode;
    return {
      success: false,
      message: dbError.message,
      code: dbError.type,
      timestamp: new Date().toISOString()
    };
  }

  // 处理验证错误
  if (error.name === 'ValidationError') {
    set.status = 400;
    return {
      success: false,
      message: error.message || '请求参数验证失败',
      code: ErrorType.VALIDATION,
      timestamp: new Date().toISOString()
    };
  }

  // 处理JWT错误
  if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
    set.status = 401;
    return {
      success: false,
      message: error.name === 'TokenExpiredError' ? '令牌已过期' : '无效的令牌',
      code: ErrorType.UNAUTHORIZED,
      timestamp: new Date().toISOString()
    };
  }

  // 处理语法错误
  if (error instanceof SyntaxError) {
    set.status = 400;
    return {
      success: false,
      message: '请求格式错误',
      code: ErrorType.VALIDATION,
      timestamp: new Date().toISOString()
    };
  }

  // 处理类型错误
  if (error instanceof TypeError) {
    set.status = 400;
    return {
      success: false,
      message: '请求参数类型错误',
      code: ErrorType.VALIDATION,
      timestamp: new Date().toISOString()
    };
  }

  // 默认内部服务器错误
  set.status = 500;
  return {
    success: false,
    message: '服务器内部错误',
    error: process.env.NODE_ENV === 'development' ? error.message : undefined,
    code: ErrorType.INTERNAL_ERROR,
    timestamp: new Date().toISOString()
  };
}

/**
 * 处理数据库错误
 */
function handleDatabaseError(error: any): { message: string; statusCode: number; type: ErrorType } {
  // SQLite 错误处理
  if (error.code?.startsWith('SQLITE_')) {
    switch (error.code) {
      case 'SQLITE_CONSTRAINT_UNIQUE':
        return {
          message: '数据已存在，请检查重复项',
          statusCode: 409,
          type: ErrorType.DUPLICATE
        };
      case 'SQLITE_CONSTRAINT_FOREIGNKEY':
        return {
          message: '关联数据不存在，请检查引用关系',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case 'SQLITE_CONSTRAINT_NOTNULL':
        return {
          message: '必填字段不能为空',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case 'SQLITE_CONSTRAINT_CHECK':
        return {
          message: '数据格式不符合要求',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      default:
        return {
          message: '数据库操作失败',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
    }
  }

  // PostgreSQL 错误处理
  if (error.code?.match(/^\d{5}$/)) {
    switch (error.code) {
      case '23505': // unique_violation
        return {
          message: '数据已存在，请检查重复项',
          statusCode: 409,
          type: ErrorType.DUPLICATE
        };
      case '23503': // foreign_key_violation
        return {
          message: '关联数据不存在，请检查引用关系',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case '23502': // not_null_violation
        return {
          message: '必填字段不能为空',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case '23514': // check_violation
        return {
          message: '数据格式不符合要求',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case '42P01': // undefined_table
        return {
          message: '数据表不存在',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
      case '42703': // undefined_column
        return {
          message: '数据字段不存在',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
      default:
        return {
          message: '数据库操作失败',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
    }
  }

  // MySQL 错误处理
  if (error.errno) {
    switch (error.errno) {
      case 1062: // ER_DUP_ENTRY
        return {
          message: '数据已存在，请检查重复项',
          statusCode: 409,
          type: ErrorType.DUPLICATE
        };
      case 1452: // ER_NO_REFERENCED_ROW_2
        return {
          message: '关联数据不存在，请检查引用关系',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case 1364: // ER_NO_DEFAULT_FOR_FIELD
        return {
          message: '必填字段不能为空',
          statusCode: 400,
          type: ErrorType.VALIDATION
        };
      case 1146: // ER_NO_SUCH_TABLE
        return {
          message: '数据表不存在',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
      case 1054: // ER_BAD_FIELD_ERROR
        return {
          message: '数据字段不存在',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
      default:
        return {
          message: '数据库操作失败',
          statusCode: 500,
          type: ErrorType.INTERNAL_ERROR
        };
    }
  }

  // 通用数据库错误
  return {
    message: '数据库操作失败',
    statusCode: 500,
    type: ErrorType.INTERNAL_ERROR
  };
}

/**
 * 404 错误处理
 */
export function notFoundHandler({ set }: Context) {
  set.status = 404;
  return {
    success: false,
    message: '请求的资源不存在',
    code: ErrorType.NOT_FOUND,
    timestamp: new Date().toISOString()
  };
}

/**
 * 请求超时处理
 */
export function timeoutHandler({ set }: Context) {
  set.status = 408;
  return {
    success: false,
    message: '请求超时',
    code: 'REQUEST_TIMEOUT',
    timestamp: new Date().toISOString()
  };
}

/**
 * 请求体过大处理
 */
export function payloadTooLargeHandler({ set }: Context) {
  set.status = 413;
  return {
    success: false,
    message: '请求体过大',
    code: 'PAYLOAD_TOO_LARGE',
    timestamp: new Date().toISOString()
  };
}

/**
 * 方法不允许处理
 */
export function methodNotAllowedHandler({ set }: Context) {
  set.status = 405;
  return {
    success: false,
    message: '请求方法不允许',
    code: 'METHOD_NOT_ALLOWED',
    timestamp: new Date().toISOString()
  };
}

/**
 * 请求频率限制处理
 */
export function rateLimitHandler({ set }: Context) {
  set.status = 429;
  return {
    success: false,
    message: '请求过于频繁，请稍后再试',
    code: 'RATE_LIMIT_EXCEEDED',
    timestamp: new Date().toISOString()
  };
}